#include "GrapplingArm.h"
#include "GrappleObject.h"
#include "GameObject.h"
#include "ObjectManager.h"
#include "GamePlayState.h"
#include "..\SGD Wrappers\CSGD_TextureManager.h"
#include "Camera.h"
#include "AudioManager.h"
#include "Arm.h"
#include "ToolManager.h"


GrapplingArm::GrapplingArm(void)
{
	grapplebody = new GrappleObject(this);
	ObjectManager::GetInstance()->AddObject(4, grapplebody);
	ImageLR = CSGD_TextureManager::GetInstance()->LoadTexture("Textures\\Objects\\GrappleLR.png");
	ImageUD = CSGD_TextureManager::GetInstance()->LoadTexture("Textures\\Objects\\GrappleUD.png");
	hasAttached = false;
	isDisabled = false;
	GamePlayState::GetInstance()->GetPlayer();
}

GrapplingArm::~GrapplingArm(void)
{
}

void GrapplingArm::Update( float deltaTime )
{
	if(isActive && !isDisabled)
	{
		float tempwidth = (float)hitbox.right - hitbox.left;
		float tempheight = (float)hitbox.bottom - hitbox.top;

		if( currState == EXTENDING)
		{
			if(direction == Left)
			{
				hitbox.top = (long)arm->GetToolPointY();
				hitbox.bottom = (long)arm->GetToolPointY() + CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR);
				hitbox.top -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.bottom -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.right = (long)arm->GetToolPointX();
				hitbox.left = hitbox.right - (long)tempwidth;

				hitbox.left -= (long)(250 * deltaTime);
				drawbox.left -= (long)(250 * deltaTime);
			}
			else if(direction == Right)
			{
				hitbox.top = (long)arm->GetToolPointY();
				hitbox.bottom = (long)arm->GetToolPointY() + CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR);
				hitbox.top -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.bottom -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.left = (long)arm->GetToolPointX();
				hitbox.right = hitbox.left + (long)tempwidth;

				hitbox.right += (long)(250 * deltaTime);
				drawbox.left -= (long)(250 * deltaTime);
			}
			else if(direction == Down)
			{
				hitbox.left = (long)arm->GetToolPointX();
				hitbox.right = (long)arm->GetToolPointX() + CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD);
				hitbox.left -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.right -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.top = (long)arm->GetToolPointY();
				hitbox.bottom = hitbox.top + (long)tempheight;

				hitbox.bottom += (long)(250 * deltaTime);
				drawbox.bottom += (long)(250 * deltaTime);			
				sizeoffset = (float)drawbox.bottom - drawbox.top;
			}
			else if(direction == Up)
			{
				hitbox.left = (long)arm->GetToolPointX();
				hitbox.right = (long)arm->GetToolPointX() + CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD);
				hitbox.left -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.right -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.bottom = (long)arm->GetToolPointY();
				hitbox.top = hitbox.bottom - (long)tempheight;

				hitbox.top -= (long)(250 * deltaTime);
				drawbox.bottom += (long)(250 * deltaTime);
				sizeoffset = (float)drawbox.bottom - drawbox.top;
			}
			grapplebody->SetHitBox(hitbox);
			grapplebody->SetPosX((float)hitbox.left);
			grapplebody->SetPosY((float)hitbox.top);

			if( drawbox.right - drawbox.left >= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageLR) || drawbox.bottom - drawbox.top >= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageUD) )
				currState = RETRACTING;
		}

		else if( currState == RETRACTING )
		{
			if(direction == Left)
			{
				hitbox.top = (long)arm->GetToolPointY();
				hitbox.bottom = (long)arm->GetToolPointY() + CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR);
				hitbox.top -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.bottom -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.right = (long)arm->GetToolPointX();
				hitbox.left = hitbox.right - (long)tempwidth;

				hitbox.left += (long)(250 * deltaTime);
				drawbox.left += (long)(250 * deltaTime);
			}
			else if(direction == Right)
			{
				hitbox.top = (long)arm->GetToolPointY();
				hitbox.bottom = (long)arm->GetToolPointY() + CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR);
				hitbox.top -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.bottom -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.left = (long)arm->GetToolPointX();
				hitbox.right = hitbox.left + (long)tempwidth;

				hitbox.right -= (long)(250 * deltaTime);
				drawbox.left += (long)(250 * deltaTime);
			}
			else if(direction == Down)
			{
				hitbox.left = (long)arm->GetToolPointX();
				hitbox.right = (long)arm->GetToolPointX() + CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD);
				hitbox.left -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.right -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.top = (long)arm->GetToolPointY();
				hitbox.bottom = hitbox.top + (long)tempheight;

				hitbox.bottom -= (long)(250 * deltaTime);
				drawbox.bottom -= (long)(250 * deltaTime);			
				sizeoffset = (float)drawbox.bottom - drawbox.top;
			}
			else if(direction == Up)
			{
				hitbox.left = (long)arm->GetToolPointX();
				hitbox.right = (long)arm->GetToolPointX() + CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD);
				hitbox.left -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.right -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.bottom = (long)arm->GetToolPointY();
				hitbox.top = hitbox.bottom - (long)tempheight;

				hitbox.top += (long)(250 * deltaTime);
				drawbox.bottom -= (long)(250 * deltaTime);
				sizeoffset = (float)drawbox.bottom - drawbox.top;
			}
			grapplebody->SetHitBox(hitbox);
			grapplebody->SetPosX((float)hitbox.left);
			grapplebody->SetPosY((float)hitbox.top);

			if( drawbox.right - drawbox.left <= 4 || drawbox.bottom - drawbox.top <= 4 )
			{
				currState = IDLE;
				GamePlayState::GetInstance()->GetPlayer()->GetToolManager()->ToggleTool(GRAPPLE);
			}
		}
		else if( currState == ATTACHED )
		{
			if(direction == Left)
			{
				GamePlayState::GetInstance()->GetPlayer()->SetPosX( objectAttached->GetHitBox().right + DifferenceX );
				GamePlayState::GetInstance()->GetPlayer()->SetPosY( objectAttached->GetPosY() + DifferenceY );
				hitbox.top = (long)arm->GetToolPointY();
				hitbox.bottom = (long)arm->GetToolPointY() + CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR);
				hitbox.top -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.bottom -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.right = (long)arm->GetToolPointX();
				hitbox.left = objectAttached->GetHitBox().right;

				drawbox.left = drawbox.right - (hitbox.right - hitbox.left);
			}
			else if(direction == Right)
			{
				GamePlayState::GetInstance()->GetPlayer()->SetPosX( objectAttached->GetHitBox().left + DifferenceX );
				GamePlayState::GetInstance()->GetPlayer()->SetPosY( objectAttached->GetPosY() + DifferenceY );
				hitbox.top = (long)arm->GetToolPointY();
				hitbox.bottom = (long)arm->GetToolPointY() + CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR);
				hitbox.top -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.bottom -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
				hitbox.left = (long)arm->GetToolPointX();
				hitbox.right = objectAttached->GetHitBox().left;

				drawbox.left = drawbox.right - (hitbox.right - hitbox.left);
			}
			else if(direction == Down)
			{
				GamePlayState::GetInstance()->GetPlayer()->SetPosX( objectAttached->GetPosX() + DifferenceX );
				GamePlayState::GetInstance()->GetPlayer()->SetPosY( objectAttached->GetHitBox().top + DifferenceY);
				hitbox.left = (long)arm->GetToolPointX();
				hitbox.right = (long)arm->GetToolPointX() + CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD);
				hitbox.left -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.right -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.top = (long)arm->GetToolPointY();
				hitbox.bottom = objectAttached->GetHitBox().top;

				drawbox.bottom = hitbox.bottom - hitbox.top;
				sizeoffset = (float)drawbox.bottom - drawbox.top;
			}
			else if(direction == Up)
			{
				GamePlayState::GetInstance()->GetPlayer()->SetPosX( objectAttached->GetPosX() + DifferenceX);
				GamePlayState::GetInstance()->GetPlayer()->SetPosY( objectAttached->GetHitBox().bottom + DifferenceY);
				hitbox.left = (long)arm->GetToolPointX();
				hitbox.right = (long)arm->GetToolPointX() + CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD);
				hitbox.left -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.right -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
				hitbox.bottom = (long)arm->GetToolPointY();
				hitbox.top = objectAttached->GetHitBox().bottom;

				drawbox.bottom = hitbox.bottom - hitbox.top;
				sizeoffset = (float)drawbox.bottom - drawbox.top;
			}
			grapplebody->SetHitBox(hitbox);
			grapplebody->SetPosX((float)hitbox.left);
			grapplebody->SetPosY((float)hitbox.top); 
		}
	}
}

void GrapplingArm::Render( void ) const
{
	if(isActive)
	{
		if(direction == Left)
		{
			CSGD_TextureManager::GetInstance()->Draw(ImageLR, (int)arm->GetToolPointX() - (int)Camera::GetInstance()->OffsetX(),
				(int)arm->GetToolPointY() - (CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2) - (int)Camera::GetInstance()->OffsetY(),
				-1, 1, &drawbox);
		}
		else if(direction == Right)
		{
			CSGD_TextureManager::GetInstance()->Draw(ImageLR, (int)arm->GetToolPointX() - (int)Camera::GetInstance()->OffsetX(),
				(int)arm->GetToolPointY() - (CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2) - (int)Camera::GetInstance()->OffsetY(),
				1, 1, &drawbox);
		}
		else if(direction == Up)
		{
			CSGD_TextureManager::GetInstance()->Draw(ImageUD, (int)arm->GetToolPointX() - (int)CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2 - (int)Camera::GetInstance()->OffsetX(),
				(int)arm->GetToolPointY() - (int)sizeoffset - (int)Camera::GetInstance()->OffsetY(), 1, 1, &drawbox);
		}
		else if(direction == Down)
		{
			CSGD_TextureManager::GetInstance()->Draw(ImageUD, (int)arm->GetToolPointX() - CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2 - (int)Camera::GetInstance()->OffsetX(),
				(int)arm->GetToolPointY() + (int)sizeoffset - (int)Camera::GetInstance()->OffsetY(), 1, -1, &drawbox);
		}
	}
}

void GrapplingArm::Disable( void )
{
	isDisabled = true;
}

void GrapplingArm::Enable( void )
{
	isDisabled = false;
}

void GrapplingArm::ActivateTool( Arm* arm )
{
	isActive = true;
	this->arm = arm;
	currState = EXTENDING;
	hasAttached = false;

	//Play sound effect
	AudioManager::GetInstance()->playSFX("grapple_activate");

	playerpreviousposX = (float)arm->GetToolPointX();
	playerpreviousposY = (float)arm->GetToolPointY();

	if(GamePlayState::GetInstance()->GetPlayer()->GetHeading().fY == 0 && GamePlayState::GetInstance()->GetPlayer()->GetHeading().fX == -1)
	{
		direction = Right;
		hitbox.left = (long)arm->GetToolPointX();
		hitbox.right = (long)arm->GetToolPointX();
		hitbox.top = (long)arm->GetToolPointY();
		hitbox.bottom = (long)arm->GetToolPointY() + CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR);
		hitbox.top -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
		hitbox.bottom -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
		drawbox.right = drawbox.left = CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageLR);
		drawbox.top = 0;
		drawbox.bottom = CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR);
	}
	else if(GamePlayState::GetInstance()->GetPlayer()->GetHeading().fY == 0 && GamePlayState::GetInstance()->GetPlayer()->GetHeading().fX == 1)
	{
		direction = Left;
		hitbox.left = (long)arm->GetToolPointX();
		hitbox.right = (long)arm->GetToolPointX();
		hitbox.top = (long)arm->GetToolPointY();
		hitbox.bottom = (long)arm->GetToolPointY() + CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR);
		hitbox.top -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
		hitbox.bottom -= CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR)/2;
		drawbox.right = drawbox.left = CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageLR);
		drawbox.top = 0;
		drawbox.bottom = CSGD_TextureManager::GetInstance()->GetTextureHeight(ImageLR);
	}
	else if(GamePlayState::GetInstance()->GetPlayer()->GetHeading().fY == 1 )
	{
		direction = Up;
		hitbox.left = (long)arm->GetToolPointX();
		hitbox.right = (long)arm->GetToolPointX() + CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD);
		hitbox.left -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
		hitbox.right -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
		hitbox.top = (long)arm->GetToolPointY();
		hitbox.bottom = (long)arm->GetToolPointY();
		drawbox.left = 0;
		drawbox.right = CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD);
		drawbox.top = drawbox.bottom = 0;
	}
	else if(GamePlayState::GetInstance()->GetPlayer()->GetHeading().fY == -1 )
	{
		direction = Down;
		hitbox.left = (long)arm->GetToolPointX();
		hitbox.right = (long)arm->GetToolPointX() + CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD);
		hitbox.top = (long)arm->GetToolPointY();
		hitbox.bottom = (long)arm->GetToolPointY();
		hitbox.left -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
		hitbox.right -= CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD)/2;
		drawbox.left = 0;
		drawbox.right = CSGD_TextureManager::GetInstance()->GetTextureWidth(ImageUD);
		drawbox.top = drawbox.bottom = 0;
	}

	grapplebody->SetHitBox(hitbox);
}

void GrapplingArm::DeactivateTool( void )
{
	isActive = false;
	hasAttached = false;

	grapplebody->SetPosX(0);
	grapplebody->SetPosY(0);

	drawbox.left = hitbox.left = 0; 
	drawbox.right = hitbox.right =	0; 
	drawbox.top = hitbox.top = 0;
	drawbox.bottom = hitbox.bottom = 0;

	grapplebody->SetHitBox(hitbox);
	GamePlayState::GetInstance()->GetPlayer()->SetLocked(false);
}

void GrapplingArm::CollideNoAttach( void )
{
	currState = RETRACTING;
}

void GrapplingArm::SideCollide( void )
{
	currState = IDLE;
	GamePlayState::GetInstance()->GetPlayer()->GetToolManager()->ToggleTool(GRAPPLE);
}

void GrapplingArm::SetAttached( GameObject* object )
{
	currState = ATTACHED;
	hasAttached = true;
	objectAttached = object;

	Player* player = GamePlayState::GetInstance()->GetPlayer();

	//Play sound effect
	AudioManager::GetInstance()->playSFX("grapple_attach");

	switch(direction)
	{
	case Up:
		GamePlayState::GetInstance()->GetPlayer()->SetPosY(GamePlayState::GetInstance()->GetPlayer()->GetPosY() - 15);

		DifferenceX = GamePlayState::GetInstance()->GetPlayer()->GetPosX() - objectAttached->GetPosX();
		DifferenceY = GamePlayState::GetInstance()->GetPlayer()->GetPosY() - objectAttached->GetHitBox().bottom;
		player->SetHitBox( Physics::UpdateColRect( player->GetHitBox(), (int)player->GetPosX(),(int) player->GetPosY()));
		break;
	case Down:
		GamePlayState::GetInstance()->GetPlayer()->SetPosY(GamePlayState::GetInstance()->GetPlayer()->GetPosY() - 15);
		//GamePlayState::GetInstance()->GetPlayer()->SetIsGrounded(true);
		DifferenceX = GamePlayState::GetInstance()->GetPlayer()->GetPosX() - objectAttached->GetPosX();
		DifferenceY = GamePlayState::GetInstance()->GetPlayer()->GetPosY() - objectAttached->GetHitBox().top;
		player->SetHitBox( Physics::UpdateColRect( player->GetHitBox(), (int)player->GetPosX(), (int)player->GetPosY()));
		break;
	case Right:
		DifferenceX = GamePlayState::GetInstance()->GetPlayer()->GetPosX() - objectAttached->GetHitBox().left;
		DifferenceY = GamePlayState::GetInstance()->GetPlayer()->GetPosY() - objectAttached->GetPosY();
		break;
	case Left:
		DifferenceX = GamePlayState::GetInstance()->GetPlayer()->GetPosX() - objectAttached->GetHitBox().right;
		DifferenceY = GamePlayState::GetInstance()->GetPlayer()->GetPosY() - objectAttached->GetPosY();
		break;
	}
	GamePlayState::GetInstance()->GetPlayer()->SetLocked(true);
	GamePlayState::GetInstance()->GetPlayer()->SetDir(direction);
}